home *** CD-ROM | disk | FTP | other *** search
/ Turnbull China Bikeride / Turnbull China Bikeride - Disc 2.iso / STUTTGART / LANG / C / LIB / UNIXLIB37B / !UnixLib37 / src / c / mktime < prev    next >
Text File  |  1996-11-09  |  4KB  |  190 lines

  1. /****************************************************************************
  2.  *
  3.  * $Source: /unixb/home/unixlib/source/unixlib37/src/c/RCS/mktime,v $
  4.  * $Date: 1996/04/19 21:26:42 $
  5.  * $Revision: 1.1 $
  6.  * $State: Rel $
  7.  * $Author: simon $
  8.  *
  9.  * $Log: mktime,v $
  10.  * Revision 1.1  1996/04/19 21:26:42  simon
  11.  * Initial revision
  12.  *
  13.  ***************************************************************************/
  14.  
  15. static const char rcs_id[] = "$Id: mktime,v 1.1 1996/04/19 21:26:42 simon Rel $";
  16.  
  17. #include <time.h>
  18. #include <stdio.h>
  19. #include <ctype.h>
  20. #include <stdlib.h>
  21.  
  22. static unsigned int __tmonth[12] =
  23. {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
  24.  
  25. struct tm __tz[1] =        /* time struct */
  26. {
  27.   {0, 0, 0, 0, 0, 0, 0, 0, -1, 0, ""}
  28. };
  29.  
  30. /* Time zones are "[TZNAME][H][:M][DSTNAME]" where H:M gives the time *west*
  31.  * of GMT for the timezone. If DSTNAME appears then the time zone follows
  32.  * DST rules according to DSTNAME. Examples:
  33.  *
  34.  * "EST5EDT"            USA Eastern time zone
  35.  * "CST6CDT"            USA Central time zone
  36.  * "NFLDT3:30NFLD"      Newfoundland time (1:30 ahead of Eastern)
  37.  * "OZCST-9:30"         Australian Central time zone (no DST)
  38.  *
  39.  * DST is currently unimplemented: Other implementations involve very nasty
  40.  * code in order to cater for exception years (e.g. USA 1972). Also most
  41.  * assume USA rules for DST (which have changed 3 times since 1970), not UK
  42.  * rules (which have changed more often and are more complex :-( ). It's
  43.  * simpler to rely on the SysAdmin changing the system clock twice a year
  44.  * according to local custom. Leap seconds and the century offset are ignored,
  45.  * but the routines are correct to within a second till at least 2038... */
  46.  
  47. int timezone = 0;
  48.  
  49. void
  50. tzset (void)
  51. {
  52.   char *z;
  53.   register int i;
  54.  
  55.   if (!(z = getenv ("TZ")))
  56.     z = "GMT0UK";        /* default to GMT/UKDST */
  57.  
  58.   i = 0;
  59.   while (isalpha (*z))
  60.     {
  61.       if (i < 3)
  62.     {
  63.       __tz->tm_zone[i] = *z;
  64.       i++;
  65.     }
  66.       z++;
  67.     }
  68.   __tz->tm_zone[i] = 0;
  69.  
  70.   i = (int) strtol (z, &z, 10) * 3600;
  71.   if (*z == ':')
  72.     {
  73.       z++;
  74.       i += (int) strtol (z, &z, 10) * 60;
  75.     }
  76.  
  77.   __tz->tm_gmtoff = timezone = i;
  78. }
  79.  
  80. static struct tm *__mktm (register time_t);
  81.  
  82. struct tm *
  83. gmtime (register const time_t * tp)
  84. {
  85.   if (!(__tz->tm_zone[0]))
  86.     tzset ();
  87.  
  88.   return (__mktm (*tp));
  89. }
  90.  
  91. struct tm *
  92. localtime (register const time_t * tp)
  93. {
  94.   if (!(__tz->tm_zone[0]))
  95.     tzset ();
  96.  
  97.   return (__mktm ((*tp) - __tz->tm_gmtoff));
  98. }
  99.  
  100. static struct tm *
  101. __mktm (register time_t tm)
  102. {
  103.   register struct tm *t = __tz;
  104.   register time_t i, j, k;
  105.  
  106.   t->tm_isdst = -1;
  107.  
  108.   t->tm_wday = (tm / 86400 + 4) % 7;    /* 1st Jan 1970 = Thursday */
  109.  
  110.   t->tm_sec = tm % 60;
  111.   tm /= 60;
  112.   t->tm_min = tm % 60;
  113.   tm /= 60;
  114.   t->tm_hour = tm % 24;
  115.   tm /= 24;
  116.  
  117.   i = (365 << 1);        /* two years */
  118.  
  119.   if (tm >= i)            /* >= 1972 */
  120.     {
  121.       j = (tm - i) / 1461;
  122.       tm -= i + j * 1461;
  123.       k = tm ? ((tm - 1) / 365) : 0;
  124.       if (k)
  125.     {
  126.       tm -= 1 + k * 365;
  127.       __tmonth[1] = 28;
  128.     }
  129.       else
  130.     __tmonth[1] = 29;    /* Feb. hath 29 days in a leap year */
  131.       k += 2 + (j << 2);
  132.     }
  133.   else
  134.     /* < 1972 */
  135.     {
  136.       k = tm / 365;
  137.       tm -= k * 365;
  138.       __tmonth[1] = 28;
  139.     }
  140.  
  141.   t->tm_year = k + 70;
  142.   t->tm_yday = tm;
  143.  
  144.   k = tm;
  145.   j = 0;
  146.   while (k >= (i = __tmonth[j]))
  147.     k -= i, j++;
  148.  
  149.   t->tm_mon = j;
  150.   t->tm_mday = k + 1;
  151.  
  152.   return (t);
  153. }
  154.  
  155. time_t
  156. mktime (register struct tm * t)
  157. {
  158.   register time_t r;
  159.  
  160.   if ((t->tm_year - 70) < 0)
  161.     return ((time_t) - 1);
  162.  
  163.   r = t->tm_year - 70;
  164.  
  165.   if (r < 2)
  166.     r = r * 365;
  167.   else
  168.     {
  169.       register int i, j;
  170.  
  171.       i = (r - 2) & 3;
  172.       j = ((r - 2) >> 2) * 1461;
  173.       if (i)
  174.     {
  175.       r = (365 << 1) + j + 1 + i * 365;
  176.     }
  177.       else
  178.     r = (365 << 1) + j;
  179.     }
  180.  
  181.   r += t->tm_yday;
  182.   r = r * 24 + t->tm_hour;
  183.   r = r * 60 + t->tm_min;
  184.   r = r * 60 + t->tm_sec;
  185.  
  186.   r += t->tm_gmtoff;        /* mktime() is passed a localtime() struct */
  187.  
  188.   return (r);
  189. }
  190.